<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Validator;
use App\Http\Constant;
use Illuminate\Support\Facades\DB;
use App\Helpers\ValidatorResponse;
use App\Helpers\SuccessResponse;
use App\Http\Model\RbacRole;
use App\Http\Model\RbacNode;

class RbacRoleController extends Controller{

	public function add(Request $request){
		$validator = Validator::make($request->all(), [
			'name' => 'required|string',
		]);
		if($validator->fails()){
			return ValidatorResponse::handler($validator->errors());
		}else{
			$rbac_role_model = new RbacRole();
                        //判断此角色名称是否存在
                        $isExistsRoleName = $rbac_role_model->isExsitsRoleName($request);
                        if($isExistsRoleName > 0){
                            return SuccessResponse::transformerjson('Rbac role '.$request->input('name').' exists.',-2);
                        }
                        
			try{	
				$role_id = $rbac_role_model->createRole($request);
			}catch(\Exception $e){
                                return SuccessResponse::transformerjson('['.$e->getCode().'] '.$e->getMessage(),0);
			}
			$rtn_data = [
				'id' => $role_id,
				'name' => $request->input('name'),
			];
                        return SuccessResponse::transformerjson($rtn_data,1);
		}
	}

	public function close(Request $request){
		$role_ids = json_decode($request->input('ids'), true);
		if(0 == count($role_ids)){
			return SuccessResponse::handler('['.Constant::EC_NO_VALIDATE_RBAC_ROLE_IDS.'] No validate rbac role ids privided.');
		}else{
			$rbac_role_model = new RbacRole();
			try{
				$rbac_role_model->toggleRbacRoleStatus($role_ids, Constant::TFEX_RBAC_ROLE_STATUS_CLOSE);
			}catch(\Exception $e){
				return SuccessResponse::handler('['.$e->getCode().'] '.$e->getMessage());
			}
			$rtn_data = ['id' => $role_ids];
			return SuccessResponse::handler($rtn_data);
		}
	}

	public function open(Request $request){
		$role_ids = json_decode($request->input('ids'), true);
		if(0 == count($role_ids)){
			return SuccessResponse::handler('['.Constant::EC_NO_VALIDATE_RBAC_ROLE_IDS.'] No validate rbac role ids privided.');
		}else{
			$rbac_role_model = new RbacRole();
			try{
				$rbac_role_model->toggleRbacRoleStatus($role_ids, Constant::TFEX_RBAC_ROLE_STATUS_OPEN);
			}catch(\Exception $e){
				return SuccessResponse::handler('['.$e->getCode().'] '.$e->getMessage());
			}
			$rtn_data = ['id' => $role_ids];
			return SuccessResponse::handler($rtn_data);
		}
	}

	public function delete(Request $request){
		$role_ids = json_decode($request->input('ids'), true);
		if(0 == count($role_ids)){
                        return SuccessResponse::transformerjson('['.Constant::EC_NO_VALIDATE_RBAC_ROLE_IDS.'] No validate rbac role ids privided.',0);
		}else{
			$rbac_role_model = new RbacRole();
                        //根据角色的id获取下面所属的用户是否存在
                        $is_exists_user  = $rbac_role_model->delRoleByIds($role_ids);
                        if($is_exists_user > 0){
                            return SuccessResponse::transformerjson('The user can not delete the role under this role.',-2);
                        }
			try{
				$rbac_role_model->toggleRbacRoleStatus($role_ids, Constant::TFEX_RBAC_ROLE_STATUS_DELETE);
			}catch(\Exception $e){
                                return SuccessResponse::transformerjson('['.$e->getCode().'] '.$e->getMessage(),0);
			}
			$rtn_data = ['id' => $role_ids];
                        return SuccessResponse::transformerjson($rtn_data,1);
		}
	}

	public function listRole(Request $request){
		$is_page = intval($request->input('is_page')) == 1 ? 1 : 0;
		$show_page = intval($request->input('show_page')) == 1 ? 1 : 0;
		$current_page = intval($request->input('current_page'));
		$current_page = $current_page > 1 ? $current_page : 1;
		$page_count = intval($request['page_count']);
		$page_count = $page_count > 0 ? $page_count : 20;

		$role_status = json_decode($request->input('role_status'), true);
		if(0 == count($role_status)){
			$role_status = [
				Constant::TFEX_RBAC_ROLE_STATUS_OPEN,
				Constant::TFEX_RBAC_ROLE_STATUS_CLOSE,
			];
		}else{
			$role_status = array_values($role_status);
		}
		$keywords = trim(strval($request->input('keywords')));
		$order_by = json_decode($request->input('order_by'), true);
		if(0 != count($order_by)){
			$order_by_arr = array();
			foreach ($order_by as $key => $value) {
				if($value == 'desc' || $value == 'asc'){
					array_push($order_by_arr, $key.' '.$value);
				}else{
					continue;
				}
			}
			$order_by = implode(',', $order_by_arr);
		}else{
			$order_by = 'id desc';
		}

		if($is_page){
			$data_sql = 'select * from rbac_role';
			if($role_status || strlen($keywords)){
				$data_sql .= ' where 1=1';
				if($role_status){
					$data_sql .= ' and status in ('.implode(',', $role_status).')';
				}
				if(strlen($keywords)){
					$data_sql .= ' and ( role_name like "%'.$keywords.'%")';
				}
			}
			$data_sql .= ' order by '.$order_by;
			$limit_start = ($current_page - 1) * $page_count;
			$data_sql .= ' limit '.$limit_start.','.$page_count;
			$role_data = DB::select($data_sql);
			$page_info = array(
				'total' => count($role_data),
				'total_page' => 1,
			);
			if($show_page){
				$count_sql = 'select count(*) as total from rbac_role';
				if($role_status || strlen($keywords)){
					$count_sql .= ' where 1=1';
					if($role_status){
						$count_sql .= ' and status in ('.implode(',', $role_status).')';
					}
					if(strlen($keywords)){
						$count_sql .= ' and ( role_name like "%'.$keywords.'%" )';
					}
				}
				$role_count = DB::select($count_sql);
				$role_count = json_decode(json_encode($role_count), true);
				$page_info = array(
					'total' => $role_count[0]['total'],
					'total_page' => ceil($role_count[0]['total'] / $page_count),
				);
			}
		}else{
			$data_sql = 'select * from rbac_role';
			if($role_status || strlen($keywords)){
				$data_sql .= ' where 1=1';
				if($role_status){
					$data_sql .= ' and status in ('.implode(',', $role_status).')';
				}
				if(strlen($keywords)){
					$data_sql .= ' and ( role_name like "%'.$keywords.'%")';
				}
			}
			$data_sql .= ' order by '.$order_by;
			$data_sql .= ' limit 0,999';
			$role_data = DB::select($data_sql);
			$page_info = array(
				'total' => count($role_data),
				'total_page' => 1,
			);
		}

		$rtn_data = array(
			'where' => array(
				'is_page' => $is_page,
				'show_page' => $show_page,
				'current_page' => $current_page,
				'page_count' => $page_count,
				'order_by' => $order_by,
				'role_status' => $role_status,
				'keywords' => $keywords,
			),
			'data' => $role_data,
		);
		if($show_page){
			$rtn_data['show_page'] = $page_info;
		}
		return SuccessResponse::handler($rtn_data);
	}

	public function detail(Request $request){
		$validator = Validator::make($request->all(), [
			'id' => 'required|integer|min:1',
		]);
		if($validator->fails()){
			return ValidatorResponse::handler($validator->errors());
		}else{
			$rbac_role_model = new RbacRole();
			try{
				$role_data = $rbac_role_model->where('id', '=', $request->input('id'))->whereIn('status', [
					Constant::TFEX_RBAC_ROLE_STATUS_OPEN, Constant::TFEX_RBAC_ROLE_STATUS_CLOSE
				])->get()->toArray();
				if(0 == count($role_data)){
					throw new \Exception('No rbac role [id='.$request->input('id').'] found.', Constant::EC_RBAC_ROLE_NOT_EXISTS);
				}
			}catch(\Exception $e){
				return SuccessResponse::handler('['.$e->getCode().'] '.$e->getMessage());
			}
			return SuccessResponse::handler($role_data);
		}
	}

	public function access(Request $request){
		$validator = Validator::make($request->all(), [
			'id' => 'required|integer|min:1',
		]);
		if($validator->fails()){
			return ValidatorResponse::handler($validator->errors());
		}else{
			$rbac_role_model = new RbacRole();
			try{
				$role_data = $rbac_role_model->where('id', '=', $request->input('id'))->whereIn('status', [
					Constant::TFEX_RBAC_ROLE_STATUS_OPEN, Constant::TFEX_RBAC_ROLE_STATUS_CLOSE
				])->get();
				if(0 == count($role_data)){
					throw new \Exception('No rbac role [id='.$request->input('id').'] found.', Constant::EC_RBAC_ROLE_NOT_EXISTS);
				}
			}catch(\Exception $e){
				return SuccessResponse::handler('['.$e->getCode().'] '.$e->getMessage());
			}
			$rbac_node_model = new RbacNode();
			$rbac_nodes = $rbac_node_model->listNodes($as_navigation=false, $be_tree=false);
			$this->_initNodesRoleAccess($rbac_nodes, explode(',', $role_data[0]['role_nodes']));
			foreach ($rbac_nodes as &$node) {
				unset($node['created_at']);
				unset($node['updated_at']);
				unset($node['status']);
			}
			if($request->input('be_tree') == 1){
				$rbac_nodes = $this->_getTree($rbac_nodes, 0);
			}
			return SuccessResponse::handler($rbac_nodes);
		}
	}

	public function setAccess(Request $request){
		$validator = Validator::make($request->all(), [
			'id' => 'required|integer|min:1',
		]);
		if($validator->fails()){
			return ValidatorResponse::handler($validator->errors());
		}else{
			$access_nodes_id = json_decode($request->input('access_node'), true);
			// 验证角色权限是否为空
			if(0 == count($access_nodes_id)){
				return SuccessResponse::handler('['.Constant::EC_RBAC_ROLE_ACCESS_EMPTY.'] Rbac role access can not be empty.');
			}else{	
				$rbac_role_model = new RbacRole();
				$update_data = ['role_nodes'=>implode(',', array_values($access_nodes_id))];
				try{
					$update_res = $rbac_role_model->where('id', '=', $request->input('id'))->whereIn('status', [
						Constant::TFEX_RBAC_ROLE_STATUS_OPEN, Constant::TFEX_RBAC_ROLE_STATUS_CLOSE
					])->update($update_data);
				}catch(\Exception $e){
					return SuccessResponse::handler('['.$e->getCode().'] '.$e->getMessage());
				}
				$rtn_data = [
					'id' => $request->input('id'),
					'access_node' => $access_nodes_id,
					'res' => $update_res,
				];
				return SuccessResponse::handler($rtn_data);
			}
		}
	}

	public function _initNodesRoleAccess(&$nodes, $access){
		foreach ($nodes as &$node) {
			$access_node = 0;
			if(false !== ($key = array_search($node['id'], $access))){
				$access_node = 1;
				unset($access[$key]);
			}
			$node['_access'] = $access_node;
		}
	}

	private function _getTree($nodes, $pid=0){
		$sub_nodes = array();
		foreach ($nodes as $value) {
			if($value['pid'] == $pid){
				$sub_nodes_data = $this->_getTree($nodes, $value['id']);
				if(0 != count($sub_nodes_data)){
					$value['_sub'] = $sub_nodes_data;
				}
				array_push($sub_nodes, $value);
			}else{
				continue;
			}
		}
		return $sub_nodes;
	}
}